﻿using System;
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]
public class RunnerCharacter : MonoBehaviour
{

    public enum RunnerStatus
    {
        Running,
        Jumping,
        Sliding,
        Dead
    }

    private static RunnerCharacter _instance = null;

    public RaycastCollider2D headCheck = new RaycastCollider2D(RaycastCollider2D.TypeOfCollider.Overhead);
    public RaycastCollider2D footCheck = new RaycastCollider2D(RaycastCollider2D.TypeOfCollider.Underfoot);

    public float HP = 10;

    public float runSpeed = 2.0f;
    public float jumpSpeed = 8.0f;

    public RunnerStatus status = RunnerStatus.Dead;
    private Rigidbody2D rigid;

    private Vector2 velocity;

    private bool isSliding = false;
    private Vector3 oriPosition;

    private float maxHP;

    public RunnerCharacter Instance
    {
        get { return _instance; }
    }
    public RunnerStatus Status
    {
        get
        {
            return status;
        }

    }
    public Vector2 Velocity
    {
        get
        {
            return velocity;
        }
    }


    void OnValidate()
    {
        if (headCheck.Target == null)
            headCheck.Target = transform;
        if (footCheck.Target == null)
            footCheck.Target = transform;
    }

    void Awake()
    {
        _instance = this;

        rigid = GetComponent<Rigidbody2D>();

        oriPosition = transform.position;
        maxHP = HP;

    }

    void OnEnable()
    {
        GameManager.Instance.OverEvents += Dead;
        GameManager.Instance.ResetEvents += Reset;
    }

    void OnDisable()
    {
        GameManager.Instance.OverEvents -= Dead;
        GameManager.Instance.ResetEvents -= Reset;
    }

    void Start()
    {

    }

    void Update()
    {
        StatusCheck();
    }

    void FixedUpdate()
    {
        Run();
    }

    public void Run()
    {
        if (status == RunnerStatus.Dead) return;

        rigid.velocity = new Vector2(runSpeed, rigid.velocity.y);
        velocity = rigid.velocity;
    }

    public void Jump()
    {
        if (status == RunnerStatus.Dead) return;

        if (IsGrounded() && !IsHeadHit() && status != RunnerStatus.Jumping)
            status = RunnerStatus.Jumping;

        if (status == RunnerStatus.Jumping && IsGrounded())
            rigid.velocity = new Vector2(rigid.velocity.x, jumpSpeed);
    }

    public void Slide(bool button)
    {
        if (status == RunnerStatus.Dead) return;

        isSliding = button;
        if (IsGrounded() && status != RunnerStatus.Sliding && isSliding)
            status = RunnerStatus.Sliding;
    }

    public void StatusCheck()
    {
        switch (status)
        {
            case RunnerStatus.Running:
                if (!IsGrounded()) status = RunnerStatus.Jumping;
                break;
            case RunnerStatus.Jumping:
                if (IsGrounded()) status = RunnerStatus.Running;
                break;
            case RunnerStatus.Sliding:
                if (!IsGrounded()) status = RunnerStatus.Jumping;
                if (!isSliding && !IsHeadHit()) status = RunnerStatus.Running;
                break;
            case RunnerStatus.Dead:
                break;
        }
    }

    public void Damage(float value)
    {
        HP -= value;
        if (HP <= 0)
        {
            HP = 0;
            GameManager.Instance.GameOver();
        }
        GameManager.Instance.UpdatePlayerHP(PercentageHP());
    }

    public void Cure(float value)
    {
        HP += value;
        if (HP >= maxHP)
        {
            HP = maxHP;
        }
        GameManager.Instance.UpdatePlayerHP(PercentageHP());
    }

    public float PercentageHP()
    {
        return HP/maxHP;
    }

    public void Dead()
    {
        status = RunnerStatus.Dead;
        rigid.velocity = Vector2.zero;
    }

    public void Reset()
    {
        status = RunnerStatus.Running;
        transform.position = oriPosition;
        HP = maxHP;
        GameManager.Instance.UpdatePlayerHP(PercentageHP());
    }


    public bool IsGrounded()
    {
        return footCheck.IsColliding();
    }

    public bool IsHeadHit()
    {
        return headCheck.IsColliding();
    }

    void OnDrawGizmos()
    {
        headCheck.DrawRayCast();
        footCheck.DrawRayCast();
    }

}


